package main

import (
	"errors"
	"fmt"
)

// 抽象组件接口
type Handler interface {
	HandleRequest(req string) (string, error)
}

// ---------------------- 基础实现：核心处理器 ----------------------
type CoreHandler struct{}

func (h *CoreHandler) HandleRequest(req string) (string, error) {
	// 模拟业务处理
	return fmt.Sprintf("处理结果: %s", req), nil
}

// ---------------------- 装饰器基类（实现接口继承） ----------------------
type BaseDecorator struct {
	handler Handler
}

func (d *BaseDecorator) HandleRequest(req string) (string, error) {
	return d.handler.HandleRequest(req)
}

// ---------------------- 具体装饰器1：认证校验 ----------------------
type AuthDecorator struct {
	BaseDecorator
	apiKey string
}

func NewAuthDecorator(h Handler, key string) *AuthDecorator {
	return &AuthDecorator{
		BaseDecorator: BaseDecorator{handler: h},
		apiKey:        key,
	}
}

func (d *AuthDecorator) HandleRequest(req string) (string, error) {
	if d.apiKey != "SECRET_KEY" {
		return "", errors.New("认证失败")
	}
	fmt.Println("[Auth] 认证通过")
	return d.BaseDecorator.HandleRequest(req)
}

// ---------------------- 具体装饰器2：日志记录 ----------------------
type LogDecorator struct {
	BaseDecorator
}

func NewLogDecorator(h Handler) *LogDecorator {
	return &LogDecorator{BaseDecorator: BaseDecorator{handler: h}}
}

func (d *LogDecorator) HandleRequest(req string) (string, error) {
	fmt.Printf("[Log] 收到请求: %s\n", req)
	res, err := d.BaseDecorator.HandleRequest(req)
	if err != nil {
		fmt.Printf("[Log] 处理失败: %v\n", err)
	} else {
		fmt.Printf("[Log] 返回结果: %s\n", res)
	}
	return res, err
}

// ---------------------- 具体装饰器3：响应压缩 ----------------------
type GzipDecorator struct {
	BaseDecorator
}

func NewGzipDecorator(h Handler) *GzipDecorator {
	return &GzipDecorator{BaseDecorator: BaseDecorator{handler: h}}
}

func (d *GzipDecorator) HandleRequest(req string) (string, error) {
	res, err := d.BaseDecorator.HandleRequest(req)
	// 模拟压缩过程
	return fmt.Sprintf("GZIP(%s)", res), err
}

// ---------------------- 客户端调用 ----------------------
func main() {
	// 构建装饰器链：日志 -> 认证 -> 压缩 -> 核心处理器 传递的过程中其实是创建了一个新对象并把旧对象嵌套在里面
	var handler Handler = &CoreHandler{}
	handler = NewGzipDecorator(handler)
	fmt.Println(handler)
	handler = NewAuthDecorator(handler, "SECRET_KEY")
	fmt.Println(handler)
	handler = NewLogDecorator(handler)
	fmt.Println(handler)

	// 发送请求
	res, _ := handler.HandleRequest("订单数据")
	fmt.Println("最终响应:", res)
}
